//: Playground - noun: a place where people can play

import UIKit

//: # swfit 读书笔记

//: ### 自动引用计数的工作机制 : 和 oc 一样通过引用计数

//: ### 自动引用计数实践
class Person{
    let name:String
    init(name:String) {
        self.name = name
        print("Person 被创建了")
    }
    
    deinit {
        print("Person 被释放了")
    }
}

var referenceOne = Person (name: "帅哥")

//: ### 弱引用 : 加上weak关键字表明这是一个弱引用
//: note 当 ARC 设置弱引用为nil时，属性观察不会被触发。

class PersonWeak {
    let name: String
    init(name: String) { self.name = name }
    var apartment: ApartmentWeak?
    deinit { print("\(name) is being deinitialized") }
}

class ApartmentWeak {
    let unit: String
    init(unit: String) { self.unit = unit }
    weak var tenant: PersonWeak?
    deinit { print("Apartment \(unit) is being deinitialized") }
}

var john: PersonWeak?
var unit4A: ApartmentWeak?

john = PersonWeak(name: "John Appleseed")
unit4A = ApartmentWeak(unit: "4A")

john!.apartment = unit4A
unit4A!.tenant = john


//: ### 无主引用 : 加上关键字unowned表示这是一个无主引用
//: note 使用无主引用，你必须确保引用始终指向一个未销毁的实例。如果你试图在实例被销毁后，访问该实例的无主引用，会触发运行时错误
//: 解释 ： Customer和CreditCard之间的关系与前面弱引用例子中Apartment和Person的关系略微不同。在这个数据模型中，一个客户可能有或者没有信用卡，但是一张信用卡总是关联着一个客户。为了表示这种关系，Customer类有一个可选类型的card属性，但是CreditCard类有一个非可选类型的customer属性

class Customer {
    let name: String
    var card: CreditCard?
    init(name: String) {
        self.name = name
    }
    deinit { print("\(name) is being deinitialized") }
}

class CreditCard {
    let number: UInt64
    unowned let customer: Customer
    init(number: UInt64, customer: Customer) {
        self.number = number
        self.customer = customer
    }
    deinit { print("Card #\(number) is being deinitialized") }
}

var john1: Customer?
john1 = Customer(name: "John Appleseed")
john1!.card = CreditCard(number: 1234_5678_9012_3456, customer: john1!)

//: ### 无主引用以及隐式解析可选属性
//: Person和Apartment的例子展示了两个属性的值都允许为nil，并会潜在的产生循环强引用。这种场景最适合用弱引用来解决。
//: Customer和CreditCard的例子展示了一个属性的值允许为nil，而另一个属性的值不允许为nil，这也可能会产生循环强引用。这种场景最适合通过无主引用来解决。
//: 然而，存在着第三种场景，在这种场景中，两个属性都必须有值，并且初始化完成后永远不会为nil。在这种场景中，需要一个类使用无主属性，而另外一个类使用隐式解析可选属性。
class Country {
    let name: String
    var capitalCity: City!
    init(name: String, capitalName: String) {
        self.name = name
        self.capitalCity = City(name: capitalName, country: self)
    }
}

class City {
    let name: String
    unowned let country: Country
    init(name: String, country: Country) {
        self.name = name
        self.country = country
    }
}

//: ### 闭包捕获列表
//: 定义捕获列表

//: 捕获列表中的每一项都由一对元素组成，一个元素是weak或unowned关键字，另一个元素是类实例的引用（例如self）或初始化过的变量（如delegate = self.delegate!）。这些项在方括号中用逗号分开。

//: 如果闭包有参数列表和返回类型，把捕获列表放在它们前面：

//:lazy var someClosure: (Int, String) -> String = {
//:   [unowned self, weak delegate = self.delegate!] (index: Int, stringToProcess: String) -> String in
//:    // 这里是闭包的函数体
//:}
//: 如果闭包没有指明参数列表或者返回类型，即它们会通过上下文推断，那么可以把捕获列表和关键字in放在闭包最开始的地方：

//:lazy var someClosure: Void -> String = {
//:    [unowned self, weak delegate = self.delegate!] in
//:       // 这里是闭包的函数体
//:}

//: 总结： 关于弱引用和无主引用
//: 如果被捕获的引用绝对不会变为nil，应该用无主引用，而不是弱引用。
//: weak self 的情况 用的比 unowned self 情况多一些 (可以蒙 weak self 不行再用 unowned self)


